package sqlx

import (
	"database/sql"
	"errors"
	"fmt"
	"gitee.com/gopher2011/sqlx/reflectx"
	"reflect"
)

// Row 是对 sql.Row 的重新实现，以便获得对 StructScan 必需的基础 sql.Rows.Columns() 数据的访问。
type Row struct {
	rows   *sql.Rows
	err    error
	unsafe bool
	Mapper *reflectx.Mapper
}

// ColumnTypes returns the underlying sql.Rows.ColumnTypes(), or the deferred error
func (r *Row) ColumnTypes() ([]*sql.ColumnType, error) {
	if r.err != nil {
		return []*sql.ColumnType{}, r.err
	}
	return r.rows.ColumnTypes()
}

// Columns 返回基础的sql.Rows.Columns()，或通常由Row.Scan() 返回的延迟错误
func (r *Row) Columns() ([]string, error) {
	if r.err != nil {
		return []string{}, r.err
	}
	return r.rows.Columns()
}

// Err returns the error encountered while scanning.
func (r *Row) Err() error {
	return r.err
}

// scan (原Scan) 是sql.Row.Scan的固定实现，它不会从内部行对象中删除基础错误（如果存在）。
func (r *Row) scan(pointer ...interface{}) error {
	if r.err != nil {
		return r.err
	}
	defer r.rows.Close()

	for _, dp := range pointer {
		if _, ok := dp.(*sql.RawBytes); ok {
			return errors.New("sql: RawBytes isn't allowed on Row.Scan")
		}
	}

	if !r.rows.Next() {
		if err := r.rows.Err(); err != nil {
			return err
		}
		return sql.ErrNoRows
	}

	err := r.rows.Scan(pointer...)
	if err != nil {
		return err
	}
	// Make sure the query can be processed to completion with no errors.
	if err1 := r.rows.Close(); err1 != nil {
		return err
	}
	return nil
}

// scanAny 参数<pointer>只能是指针类型。
func (r *Row) scanAny(pointer interface{}, structOnly bool) error {
	if r.err != nil {
		return r.err
	}
	if r.rows == nil {
		r.err = sql.ErrNoRows
		return r.err
	}
	defer r.rows.Close()

	v := reflect.ValueOf(pointer)

	// 因为 sql.Row.Scan()只能接收指针类型的参数。所以这里必须限定 pointer 只能是指针类型。
	if v.Kind() != reflect.Ptr {
		return errors.New("must pass a pointer, not a value, to StructScan destination")
	}

	if v.IsNil() {
		return errors.New("nil pointer passed to StructScan destination")
	}

	// 获取 pointer 的反射类型(即:包名+类名)，例如: main.Student。
	base := reflectx.Indirect(v.Type())

	// 如果 pointer 是结构体并且实现了 Scan(src interface{})error接口，或者不是结构体。则ok为:true。
	ok := isScan(base)

	// 如果 pointer 是结构体并且实现了 Scan(src interface{})error接口，或者不是结构体，则直接返回错误。
	if structOnly && ok {
		return structOnlyError(base)
	}

	columns, err := r.Columns() // 获取表中所有的列名。而不是列的值。
	if err != nil {
		return err
	}

	// 输出 pointer 的Kind类型，例如: int,string,并且表中至少有2列。则返回错误。
	if ok && len(columns) > 1 {
		return fmt.Errorf("scannable dest type %s with >1 columns (%d) in result", base.Kind(), len(columns))
	}

	// 如果 pointer 是 int,string...类型，并且表中只有一列。
	if ok {
		return r.scan(pointer)
	}

	m := r.Mapper

	// 获取表中列的索引。例如输出: [[0] [1] [2] [3] [4] [5]]。
	colsIndex := m.TraversalsByName(v.Type(), columns)

	if f, err1 := missingFields(colsIndex); err1 != nil && !r.unsafe {
		return fmt.Errorf("缺少目的地名称 %s in %T", columns[f], pointer)
	}
	values := make([]interface{}, len(columns))

	// 按顺序输出表中列的值的内存地址。
	err = fieldsByTraversal(v, colsIndex, values, true)
	if err != nil {
		return err
	}
	// 扫描到结构体字段指针并将其附加到我们的结果中。
	return r.scan(values...)
}

// Scan 将 Row 结果扫描进<pointer>中。<pointer>如果是结构体，则它只能是结构体的指针类型。
//  参数<pointer>如果为 nil,则底层直接调用 SliceScan()，将返回: []interface{}，error。
//  参数<pointer>如果是 map[string]interface{}类型，则底层直接调用 MapScan()，将返回: nil,error。
//  参数<pointer>如果是 *struct，则底层直接调用 Row.scanAny()，将返回: nil,error。
func (r *Row)Scan(pointer interface{})([]interface{}, error){
	if res,ok := pointer.(map[string]interface{});ok {
		return nil,MapScan(r, res)
	}
	if pointer == nil {
		return SliceScan(r)
	}
	kind := reflect.Indirect(reflect.ValueOf(pointer)).Kind()
	if kind != reflect.Struct {
		r.scan(pointer)
	}
	return nil,r.scanAny(pointer, true)
}

// Rows 是对 sql.Rows 的扩展
type Rows struct {
	*sql.Rows
	unsafe bool
	Mapper *reflectx.Mapper
	started bool // 这些字段在迭代过程中缓存行使用的内存w structScan
	fields  [][]int
	values  []interface{}
}

// ScanX (原StructScan) 类似于 sql.Rows.Scan，但是是将单个Row扫描到单个Struct中。
//  使用此方法，并在Select() 的内存负载可能过高的情况下，手动遍历Rows。
//  Rows.StructScan缓存将列位置匹配到字段的反射工作，以避免每次扫描的开销。
//  这意味着在具有不同结构类型的同一Rows实例上运行StructScan是不安全的。
//
//  参数<pointer>如果为 nil,则底层直接调用 SliceScan()，将返回: []interface{}，error。
//  参数<pointer>如果是 map[string]interface{}类型，则底层直接调用 MapScan()，将返回: nil,error。
//  参数<pointer>如果是结构体，则它只能是结构体的指针类型。
func (r *Rows) ScanX(pointer... interface{}) ([]interface{}, error) {
	if len(pointer)>1 {
		return nil,errors.New(" 只能有1个<pointer>参数，pointer个数不能超过一个!")
	}
	if len(pointer) == 0 {
		return SliceScan(r)
	}

	if res,ok := pointer[0].(map[string]interface{});ok {
		return nil,MapScan(r, res)
	}

	v := reflect.ValueOf(pointer[0])

	if v.Kind() != reflect.Ptr {
		return nil,errors.New("必须将一个指针而不是值传递给ScanX()的 <pointer>")
	}
	//kind := reflect.Indirect(reflect.ValueOf(pointer)).Kind()
	//if kind != reflect.Struct {
	//	r.Scan(pointer)
	//}
	v = v.Elem()

	if !r.started {
		columns, err := r.Columns()
		if err != nil {
			return nil,err
		}
		m := r.Mapper

		r.fields = m.TraversalsByName(v.Type(), columns)
		// 如果我们不是不安全且缺少字段，则返回错误
		if f, err1 := missingFields(r.fields); err1 != nil && !r.unsafe {
			return nil,fmt.Errorf("missing destination name %s in %T", columns[f], pointer)
		}
		r.values = make([]interface{}, len(columns))
		r.started = true
	}

	err := fieldsByTraversal(v, r.fields, r.values, true)
	if err != nil {
		return nil,err
	}
	// 扫描到struct字段指针并将其附加到我们的结果中。
	err = r.Scan(r.values...)
	if err != nil {
		return nil,err
	}
	return nil,r.Err()
}
func (r *Rows)scan(pointer ...interface{}) error{
	return nil
}
